B树的实现

本文详细介绍了B树的插入和删除算法,包括插入时的超长处理和删除时的下溢处理,同时提供了相应的代码实现。文章指出,最小的B树是2-3-4树,并给出了操作过程中的一些关键注意事项。
摘要由CSDN通过智能技术生成

B树是什么,不用说了,相信大家都懂,我今天只想详细地说一下B树的插入和删除的详细算法,为了以后自己看起来方便,并且附上自己的代码,希望对各位也能够有所帮助。

B树的插入算法:

1)用查找的方法为x找到所在的位置,查找路径终于某个空树,然后把x插入到其父结点的有序位置上,注意B树所有的插入都是在叶结点上进行。

2)如果插入x后,结点不超长,则插入完毕;否则,进入下一步,进行超长处理。

3)将超长结点一分为二,将“中间元素”递归地插入上层结点中。

4)如插入波及根,当根上溢时,把根一分为2,并将中间元素上移,而产生含单元素的新根,使B树升高。

将超长结点一分为二的操作方法:

设结点d超长,即d的元素达M个,令k=M/2向上取整,元素k作为中间元素,其左侧的元素和相应的指针仍保存在结点d中,但是需要修改d的长度,将排在k元素右侧的元素和相应的指针移入新结点e中,将k连同指向结点e的指针一起插入到d的父结点f中,排在指向结点d的指针右侧。

注意:

为了避免回溯,我的代码从上到下在查找x位置的时候,只要遇见的结点是满的,就先分解,这样,当我们插入完成后,即使需要超长处理,也只会停止在其父亲结点,不会波及更上层的结点。

我的插入代码如下:

bool CBTree::InsertNode(int nKey)
{
	int i = 0;

	if (m_Root == NULL)
	{
		/*
		如果是空树,就生成一个新的节点,修改关键字个数,设置关键字,设为叶节点,然后,修改根指针。
		*/

		BNode * pNewNode = new BNode;
		if (!pNewNode)
			return false;
		pNewNode->m_Key[0] = 1;
		pNewNode->m_Key[1] = nKey;
		pNewNode->m_bLeaf = true;
		m_Root = pNewNode;
		return true;
	}

	//非空,查找叶节点

	BNode * pCurNode = m_Root;
	BNode * pNewNode = NULL;

	BNode * pParent = NULL;
	int nParentIndex = 0;

	BNode * pChild = NULL;
	int nChildIndex = 0;

	int nMidKey = 0;
	int k = 0;

	/*
	寻找到叶节点,因为B树是在叶节点上插入,在从根节点到叶节点的路径上,如果遇见满节点,就对其进行分裂,这样的好处,就是如果
	叶节点分裂,不需要回溯,直接在父亲节点上插入即可,因为,在到达叶节点之前,已经对所有的满节点进行了分裂。
	*/

	while (pCurNode->m_bLeaf == false)
	{
		/*
		遍历当前节点的关键字,如果有相等的,就直接返回,因为已经存在了,否则,找到子树,并保存在pChild和nChildIndex。
		*/

		for (i = 1; i <= pCurNode->m_Key[0]; i++)
		{
			if (nKey == pCurNode->m_Key[i])
			{
				//已经存在,插入返回
				return true;
			}
			if (nKey < pCurNode->m_Key[1])
			{
				pChild = pCurNode->m_ChildRoot[0];
				nChildIndex = 0;
				break;
			}
			if (nKey < pCurNode->m_Key[i])
			{
				pChild = pCurNode->m_ChildRoot[i-1];	
				nChildIndex = i - 1;
				break;
			}
		}
		
		if (i > pCurNode->m_Key[0])
		{
			pChild = pCurNode->m_ChildRoot[i - 1];
			nChildIndex = pCurNode->m_Key[0];
		}

		//判断节点是否满了,如果满了则分裂。

		if (pCurNode->m_Key[0] == B_TREE_ORDER - 1)
		{
			pNewNode = new BNode;

			if (!pNewNode)
				return false;

			pNewNode->m_bLeaf = false;

			nMidKey = (B_TREE_ORDER + 1) / 2; //向上取整加1

			//拷贝关键字

			for (i = nMidKey + 1; i <= pCurNode->m_Key[0]; i++)
			{
				pNewNode->m_Key[pNewNode->m_Key[0] + 1] = pCurNode->m_Key[i];
				pNewNode->m_Key[0]++;
			}

			//拷贝孩子
			for (i = nMidKey ; i <&
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟建行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值